<template>
    <div class="upload">
        <el-upload
            ref="uploadRefs"
            :action="action"
            :multiple="multiple"
            :limit="limit"
            :show-file-list="false"
            :headers="headers"
            :data="data"
            :on-progress="handleProgress"
            :on-success="handleSuccess"
            :on-exceed="handleExceed"
            :on-error="handleError"
            :accept="getAccept"
        >
            <slot></slot>
        </el-upload>
        <!--        model-value / v-model	是否显示 Dialog-->
        <el-dialog
            v-if="showProgress && fileList.length"
            v-model="visible"
            title="上传进度"
            :close-on-click-modal="false"
            width="500px"
            :modal="false"
            @close="handleClose"
        >
            <div class="file-list p-4">
                <template v-for="(item, index) in fileList" :key="index">
                    <div class="mb-5">
                        <div>{{ item.name }}</div>
                        <div class="flex-1">
                            <el-progress :percentage="parseInt(item.percentage)"></el-progress>
                        </div>
                    </div>
                </template>
            </div>
        </el-dialog>
    </div>
</template>

<script lang="ts" setup>
import {computed, ref, shallowRef} from 'vue'
import useUserStore from '@/base/stores/modules/user'
import config from '@/config'
import feedback from '@/utils/feedback'
import type {ElUpload} from 'element-plus'
import {RequestCodeEnum} from '@/config/enums/requestEnums'

const userStore = useUserStore()


const props = withDefaults(defineProps<{
    // 上传文件类型
    type?: string
    // 是否支持多选
    multiple?: boolean
    // 多选时最多选择几条
    limit?: number
    // 上传时的额外参数
    data?: object
    // 是否显示上传进度
    showProgress?: boolean
    // mapping
    mapping?:string
    
}>(), {
    // 上传文件类型
    type: "image",
    // 是否支持多选
    multiple: true,
    // 多选时最多选择几条
    limit: 10,
    // 上传时的额外参数
    data: () => ({}),
    // 是否显示上传进度
    showProgress: false,
    // 自定义路由
    mapping:'upload'
})


/**
 * 使用上传主键方法
 */
const uploadRefs = shallowRef<InstanceType<typeof ElUpload>>()

// 上传文件请求地址
const action = ref(`${config.baseUrl}/${props.mapping}/${props.type}`)


// 上传文件http 请求头
const headers = computed(() => ({
    ['token']: userStore.token,
    version: config.version
}))


/**
 * 定义参数
 */
const visible = ref(false)
const fileList = ref<any[]>([])


const handleProgress = (event: any, file: any, fileLists: any[]) => {
    visible.value = true
    fileList.value = toRaw(fileLists)
}


/**
 * 定义事件
 */
const emit = defineEmits(['change', 'error']);

/**
 * 上传成功
 *
 * @param response
 * @param file
 * @param fileLists
 */
const handleSuccess = (response: any, file: any, fileLists: any[]) => {
    const allSuccess = fileLists.every((item) => item.status == 'success')
    if (allSuccess) {
        uploadRefs.value?.clearFiles()
        visible.value = false
        emit('change')
    }
    if (response.code == RequestCodeEnum.FAILED && response.msg) {
        feedback.msgError(response.msg)
    }
}

/**
 * 上传失败
 *
 * @param event
 * @param file
 */
const handleError = (event: any, file: any) => {
    feedback.msgError(`${file.name}文件上传失败`)
    uploadRefs.value?.abort(file)
    visible.value = false
    emit('change')
    emit('error')
}

/**
 *
 * 上传超过限定
 */
const handleExceed = () => {
    feedback.msgError(`超出上传上限${props.limit}，请重新上传`)
}

/**
 *
 * 上传取消
 */
const handleClose = () => {
    uploadRefs.value?.clearFiles()
    visible.value = false
}

/**
 * 限制上传类型
 *
 */
const getAccept = computed(() => {
    switch (props.type) {
        case 'image':
            return '.jpj,.png,.gif,.jpeg,.ico,.bmp'
        case 'video':
            return '.wmv,.avi,.mov,.mp4,.flv,.rmvb'
        case 'excel':
            return '.xls,.xlsx';
        default:
            return '*'
    }
})

</script>

